package demo.modbus.listener;

import com.serotonin.modbus4j.BasicProcessImage;
import com.serotonin.modbus4j.ModbusSlaveSet;
import com.serotonin.modbus4j.ProcessImageListener;
import demo.modbus.dto.Greeting;
import demo.modbus.dto.HoldingRegister;
import demo.modbus.dto.HoldingRegisterHandle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;

/**
 * Created by leohe on 2018/6/19.
 */
@Component
public class ModbusSalve implements CommandLineRunner {

    @Autowired
    private ModbusSlaveSet modbusSlaveSet;
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;
    @Autowired
    private HoldingRegisterHandle holdingRegisterHandle;


    @Override
    public void run(String... strings) throws Exception {

        modbusSlaveSet.addProcessImage(getModscanProcessImage(1));
        modbusSlaveSet.start();
    }

    static class BasicProcessImageListener implements ProcessImageListener {

        private HoldingRegisterHandle holdingRegisterHandle;

        private SimpMessagingTemplate simpMessagingTemplate;

        public BasicProcessImageListener() {
        }

        public BasicProcessImageListener(HoldingRegisterHandle holdingRegisterHandle,SimpMessagingTemplate simpMessagingTemplate) {
            this.holdingRegisterHandle = holdingRegisterHandle;
            this.simpMessagingTemplate = simpMessagingTemplate;
        }

        int i = 0 ;
        @Override
        public void coilWrite(int offset, boolean oldValue, boolean newValue) {
            System.out.println("Coil at " + offset + " was set from " + oldValue + " to " + newValue);
        }

        @Override
        public void holdingRegisterWrite(int offset, short oldValue, short newValue) {
            // Add a small delay to the processing.
            //            try {
            //                Thread.sleep(500);
            //            }
            //            catch (InterruptedException e) {
            //                // no op
            //            }

            //System.out.println("HR(" + i + ") at " + offset + " was set from " + oldValue + " to " + newValue);
            //i++;
            holdingRegisterHandle.save(offset,new HoldingRegister(offset,"",newValue));
            HoldingRegister holdingRegister = holdingRegisterHandle.getByOffset(offset);
            System.out.println("Address = " + holdingRegister.getAddress() + " , Value = " + holdingRegister.getValue());
            try {
                simpMessagingTemplate.convertAndSend("/topic/greetings",new Greeting("address = " + offset + " , value = " + newValue));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private BasicProcessImage getModscanProcessImage(int slaveId) {
        BasicProcessImage processImage = new BasicProcessImage(slaveId);
        //processImage.setAllowInvalidAddress(true);
        processImage.setInvalidAddressValue(Short.MIN_VALUE);
        for (int i = 0 ; i < 10 ; i++) {
            processImage.setHoldingRegister(i, (short) i);
            holdingRegisterHandle.save(i,new HoldingRegister(i,"",(short) i));
        }
        // Add an image listener.
        processImage.addListener(new BasicProcessImageListener(this.holdingRegisterHandle,this.simpMessagingTemplate));
        return processImage;
    }
}
